﻿using System;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Microsoft.Practices.Unity;
using NUnit.Framework;
using ReactiveGraph.Core;
using ReactiveGraph.Object.Configuration.Containers;

namespace ReactiveGraph.Object.Tests
{
    [TestFixture]
    public class AggregatePropertyTests
    {
        private UnityContainer _container;

        [SetUp]
        public void Setup()
        {
            _container = new UnityContainer();
            _container.AddExtension(new UnityObjectExtension());
            
        }

        [Test]
        public void CanCreateAggregate()
        {
            var root = _container.Resolve<SomeRoot>();
            root.IsValid.Value.Should().BeFalse();
            root.Foo1.IsValid.Value = true;
            root.Foo2.IsValid.Value = true;
            root.Foo3.IsValid.Value = true;
            root.IsValid.Value.Should().BeTrue();
            root.Foo3.IsValid.Value = false;
            root.IsValid.Value.Should().BeFalse();
        }

        [Test]
        public void AggregateWillTriggerValueChanges()
        {
            var root = _container.Resolve<SomeRoot>();
            root.IsValid.Value.Should().BeFalse();
            var list = new List<IProperty>();
            root.PropertyChanged(node => node.IsValid).Do(list.Add).Subscribe();
            root.Behaviours.Subscribe();
            root.Foo1.IsValid.Value = true;
            list.Should().HaveCount(0);
            root.Foo2.IsValid.Value = true;
            list.Should().HaveCount(0);
            root.Foo3.IsValid.Value = true;
            list.Should().HaveCount(1);
            root.IsValid.Value.Should().BeTrue();
            root.Foo3.IsValid.Value = false;
            list.Should().HaveCount(2);
            root.IsValid.Value.Should().BeFalse();
        }

        private class SomeRoot : ReactiveObject<SomeRoot>
        {
            public override void Initialize()
            {
                base.Initialize();
                
                IsValid = new AggregateProperty<bool>("IsValid", AllValid);
                AttachCustomProperty(IsValid);
            }

            private static bool AllValid(bool a, bool b)
            {
                return a && b;
            }

            public Foo Foo1 { get; set; }
            public Foo Foo2 { get; set; }
            public Foo Foo3 { get; set; }
            public AggregateProperty<bool> IsValid { get; set; }
        }

    }
}
